package pogvue.gui;

import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.awt.event.*;
import java.io.*;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

import pogvue.datamodel.*;
import pogvue.io.*;
import pogvue.gui.*;
import pogvue.gui.hub.*;
import pogvue.gui.event.*;
import pogvue.analysis.*;

public class SearchPanel extends JPanel implements ActionListener {
  Container    parent;

  JPanel    topPanel;
  JPanel    midPanel;
  JPanel    botPanel;
  
  JTextArea textArea;

  JButton   okButton;

  JCheckBox  tfsearch1;
  JCheckBox  tfsearch2;
  JTextField textField;
  JTextField threshField;
  JTextField infField;
  
  AlignmentI align;
  
  Controller controller;
  AlignViewport viewport;
  
  Vector mats;
  
  SearchThread searchThread = null;
  
  public SearchPanel(AlignmentI align,Controller c, AlignViewport av, Container parent) {
    this.align      = align;
    this.controller = c;
    this.viewport   = av;
    this.parent     = parent;

    topPanel  = new JPanel();
    midPanel  = new JPanel();
    botPanel  = new JPanel();
    
    FormLayout topLayout = new FormLayout("pref:grow",               // Columns
					  "pref:grow");              // Rows
    
    FormLayout midLayout = new FormLayout("pref,pref:grow",
					  "pref,pref,pref,pref,pref");

    // 3 columns
    FormLayout botLayout = new FormLayout("pref:grow, pref, pref:grow",  // Columns
					  "pref");                       // Rows
    
    topPanel.setLayout(topLayout);
    midPanel.setLayout(midLayout);
    botPanel.setLayout(botLayout);
    
    CellConstraints cc = new CellConstraints();
    
    textArea    = new JTextArea();
    tfsearch1    = new JCheckBox();
    tfsearch2    = new JCheckBox();

    tfsearch2.setSelected(true);

    textField   = new JTextField();
    threshField = new JTextField("7");
    infField    = new JTextField("0");
    
    JLabel tfLabel1     = new JLabel("Search transfac");
    JLabel tfLabel2     = new JLabel("Search for splices");
    JLabel searchLabel = new JLabel("Restrict search to matrix name (e.g. Sp1)");
    JLabel threshLabel = new JLabel("Information threshold");
    JLabel infLabel    = new JLabel("Min. matrix column information content (0-2)");

    okButton = new JButton("Ok");
    
    topPanel.add(textArea,        cc.xy(1,1, "fill, fill"));

    midPanel.add(tfsearch1,       cc.xy(2,1, "fill, fill"));
    midPanel.add(tfsearch2,       cc.xy(2,2, "fill, fill"));
    midPanel.add(textField,       cc.xy(2,3, "fill, fill"));
    midPanel.add(threshField,     cc.xy(2,4, "fill, fill"));
    midPanel.add(infField,        cc.xy(2,5, "fill, fill"));

    midPanel.add(tfLabel1,        cc.xy(1,1, "fill, fill"));
    midPanel.add(tfLabel2,        cc.xy(1,2, "fill, fill"));
    midPanel.add(searchLabel,     cc.xy(1,3, "fill, fill"));
    midPanel.add(threshLabel,     cc.xy(1,4, "fill, fill"));
    midPanel.add(infLabel,        cc.xy(1,5, "fill, fill"));

    botPanel.add(okButton,        cc.xy(2,1, "fill, fill"));   // Col 2 , Row 1
    
    setLayout(new BorderLayout());
    
    add("North", topPanel);
    add("Center",midPanel);
    add("South", botPanel);
    
    okButton.addActionListener(this);
  }

    public void actionPerformed(ActionEvent e) {
	if (e.getSource() == okButton) {
	    StringTokenizer str = new StringTokenizer(textArea.getText(),"\n");
	    
	    while (str.hasMoreTokens()) {
		String kmer = str.nextToken();
		
		Vector kmers = findKmers(align.getSequenceAt(0),kmer,viewport.getStartRes(), viewport.getEndRes());
		
		GFF gff = getGFFByName(align,kmer);
		System.out.println("Got");
		for (int i = 0;i < kmers.size(); i++) {
		    int j = ((Integer)kmers.elementAt(i)).intValue();
		    
		    gff.addFeature(new SequenceFeature(null,kmer,j,j+kmer.length(),""));
		    
		}
	    }

	    if (tfsearch1.isSelected()) {

	      double thresh = Double.parseDouble(threshField.getText());
	      double inf    = Double.parseDouble(infField.getText());

	      searchThread = new SearchThread(align,controller,viewport);

	      searchThread.setThreshold(thresh);
	      searchThread.setInfContent(inf);
	      searchThread.setSearchType("Transfac");
	      searchThread.setActionListener(this);
	      
	      if (!textField.getText().equals("")) {
		    searchThread.setNames(textField.getText());
		}
		searchThread.start();
	    }
	    if (tfsearch2.isSelected()) {

	      double thresh = Double.parseDouble(threshField.getText());
	      double inf    = Double.parseDouble(infField.getText());

	      searchThread = new SearchThread(align,controller,viewport);

	      searchThread.setThreshold(thresh);
	      searchThread.setInfContent(inf);
	      
	      searchThread.setActionListener(this);
	      searchThread.setSearchType("Splices");
	      if (!textField.getText().equals("")) {
		    searchThread.setNames(textField.getText());
		}
		searchThread.start();
	    }
	} else if (e.getSource() == searchThread) {

	  Vector out = searchThread.getOutput();
	  
	  GFF gff = getGFFByName(align,searchThread.getSearchType());
	  
	  for (int i = 0;i < out.size(); i++) {
	      gff.addFeature((SequenceFeature)out.elementAt(i));
	      //gff.addFeature(new SequenceFeature(null,kmer,j,j+kmer.length(),""));
		    
	    }

	    //	    Vector bumpgff = pogvue.io.GFFFile.bumpGFF(gff);

	    //for (int i = 0 ; i < bumpgff.size(); i++) {
	    //	GFF tmpgff = (GFF)bumpgff.elementAt(i);
	    //	GFF gffblank = new GFF("","",1,2);
	    //	align.addSequence(gffblank);	    
	    //	align.addSequence(tmpgff);	    
	    //}
	    controller.handleAlignViewportEvent(new AlignViewportEvent(this,viewport,AlignViewportEvent.COLOURING));
	    parent.setVisible(false);
	}
	    
    }

    public static GFF getGFFByName(AlignmentI align,  String name) {

	int i = 0;
	GFF gff = null;
	boolean newSequence = true;

	while (i < align.getHeight() && gff == null) {
	    if (align.getSequenceAt(i) instanceof GFF &&
		align.getSequenceAt(i).getName().equals(name)) {
		gff = (GFF)align.getSequenceAt(i);
		newSequence = false;
	    }
	    i++;
	}
	if (newSequence == true) {


	    gff = new GFF(name,"",1,2);
	    GFF gff2 = new GFF(name,"",1,2);
	    align.insertSequenceAt(gff,1);
	    align.insertSequenceAt(gff2,2);
	}

	return gff;
    }
	
  public static Vector findKmers(SequenceI seq, String kmer,int start, int end) {
	Vector out = new Vector();

	String str = seq.getSequence();

	int pos = start;
	//System.out.println("Kmer is " + kmer);
	while (pos < end && pos != -1) {
	    pos++;
	    pos = str.indexOf(kmer,pos);

	    if (pos >=1) {
	      out.addElement(pos);
	    }

	}

	str = pogvue.gui.schemes.ResidueProperties.reverseComplement(str);
	pos = start;

	int len = str.length();

	while (pos < end && pos != -1) {
	    pos++;
	    pos = str.indexOf(kmer,len-pos);

	    if (pos > 1) {
	      out.addElement(pos);
	    }

	}

	return out;
    }

    public Hashtable searchConstrainedRegions() {

	Hashtable out = new Hashtable();

	if (mats == null) {
	    try {
		mats = av.getTransfacMatrices();
	    } catch (IOException e) {
		System.out.println("Can't read TFMatrix File");
		return out;
	    }
	}

	int start = 0;
	System.out.println(" " + align.getWidth());

	while (start < align.getWidth() - 1000) {
	    int[][] intpid =  AAFrequency.calculatePID_test(align.getSequenceAt(0),
							    align.getSequences(),
							    viewport.getPIDWindow(),start,start+1000);

	    int winstart = start;

	    int mousenum = -1;

	    int i = 0;

	    while (i < align.getSequences().size()) {
		SequenceI seq = align.getSequenceAt(i);

		if (seq.getName().indexOf("ouse") > 0 ||
		    seq.getName().indexOf("mm") >= 0) {
		    mousenum = i;
		}

		i++;

	    }
		
	    if (mousenum == -1) {
		return out;
	    }
	    double thresh = 0.8;

	    int tmpstart = (int)(viewport.getPIDWindow()/2);

	    double window_mult = 100.0/(viewport.getPIDWindow()+1);

	    while (tmpstart < 1000 - 50) {

		if (intpid[tmpstart][mousenum] >= thresh*viewport.getPIDWindow()) {
		    System.out.println("Found window " + tmpstart + " " + start + " " + intpid[tmpstart][mousenum]);

		    Hashtable tmpout = searchTransfac(tmpstart+start, tmpstart+start+viewport.getPIDWindow());

		    Enumeration en = tmpout.keys();

		    while (en.hasMoreElements()) {
			String el = (String)en.nextElement();
			if (!out.containsKey(el)) {
			    Vector tmpv = new Vector();
			    out.put(el,tmpv);
			}

			Vector tmpv = (Vector)out.get(el);

			Vector tmp2 = (Vector)tmpout.get(el);

			for (int kk = 0; kk < tmp2.size(); kk++) {
			    tmpv.addElement(tmp2.elementAt(kk));
			}
		    }

		    tmpstart += viewport.getPIDWindow();
		} else {
		    tmpstart++;
		}
	    }
	    start += 1000;
	}
	return out;
    }


    public Hashtable searchTransfac(int start, int end) {
	Hashtable out = new Hashtable();

	double thresh = 0.8;

	for (int i = start; i <= end; i++) {
	    for (int j = 0; j < mats.size(); j++) {
		   
		TFMatrix tfm = (TFMatrix)mats.elementAt(j);

		double [] pwm1 = tfm.getPwm().getPwm();

		if (i+pwm1.length/4 < align.getWidth() && pwm1.length/4 > 8) {

		    String tmp = align.getSequenceAt(0).getSequence().substring(i,i+pwm1.length/4);

		    double[] seqvec = Correlation4.seqvec(new Sequence(tmp,tmp,1,tmp.length()));

		    Pwm tmppwm  = new Pwm(seqvec,"");
		    PwmCluster pwmclus = new PwmCluster(tmppwm);

		    for (int k = 1; k < align.getHeight(); k++) {
			if (align.getSequenceAt(k).getSequence().length() < i+pwm1.length/4 && 
			    align.getSequenceAt(k).getSequence().length() > 0) {
			    System.out.println("Align " + align.getSequenceAt(k).getSequence() + " "  + i);
			    tmp = align.getSequenceAt(k).getSequence().substring(i,i+pwm1.length/4);
			    seqvec = Correlation4.seqvec(new Sequence(tmp,tmp,1,tmp.length()));
			    if (tmp.indexOf("-") < 0) {
				pwmclus.addPwm(new Pwm(seqvec,""));
			    }
			}
		    } 

		    double   tmpcorr = Correlation4.get(pwm1,pwmclus.getPwm());


		    if (tmpcorr > thresh) {
			if (!out.containsKey(tfm.getName())) {
			    Vector tmpv = new Vector();
			    out.put(tfm.getName(),tmpv);
			}

			Vector tmpv = (Vector)out.get(tfm.getName());

			tmpv.add(i);

			System.out.print("Matrix " +  tfm.getName() + " " + tfm.getConsensus() + " " + i);
			System.out.print(" Consensus mat " + PwmCluster.getConsensus(pwm1));
			System.out.print(" Consensus aln " + PwmCluster.getConsensus(pwmclus.getPwm()));
			System.out.println(" Corr " + tmpcorr);	
			//System.out.println("logo\n");
			//		Pwm.printLogo(pwm1);
			//System.out.println("\nlogo\n");
			//Pwm.printLogo(pwmclus.getPwm());
			//System.out.println("\nlogo\n");
		    }
		}
	    }

	}
	return out;
    }
    public static void main(String[] args) {
	
// 	try {
// 	    FastaFile ff = new FastaFile(args[0],"File");
	    
// 	    ff.parse();
	    
// 	    SequenceI[] seqs = ff.getSeqsAsArray();
	    
// 	    Alignment align = new Alignment(seqs);

// 	    JPanel jp = GenomeInfoFactory.makePanel(al,"Pogvue",.1,10,null);
// 	    JFrame jf2 = new JFrame("Pogvue");

// 	    jf2.getContentPane().add(jp);
// 	    jf2.setSize(1000,700);
// 	    jf2.setVisible(true);

	    
// 	    JFrame jf = new JFrame("Test SearchPanel");
	    
// 	    SearchPanel sp = new SearchPanel(align,);
	    
// 	    jf.getContentPane().setLayout(new BorderLayout());
	    
// 	    jf.getContentPane().add("Center",sp);
	    
// 	    jf.setSize(500,500);
	    
// 	    jf.setVisible(true);
// 	} catch (IOException e) {
// 	    System.out.println("IOException " + e);
// 	}
    }

}
